7segment led_DE1-SoC with Linux

7 segment LED 출력 장치 예제
6개의 7 segment LED 출력장치를 /dev/hex 문자 장치 파일을 통하여 사용할 수 있도록 디바이스 드라이버를 작성
(major number=240)

write 함수는 32비트(실제로는 하위 24비트가 출력)을 6개의 7 세그먼트 LED에 16진수로 출력한다.
(하위 16비트를 4개의 7 segment LED를 위한 32비트 데이터로 변환하고, 상위 8비트를 2개의 7 segment LED를 위한
데이터로 변환)

read 함수에서는 현재 출력된 32비트의 값을 출력한다. 출력값을 변수에도 저장하고 이 값을 반환한다.

open, release함수에서는 아무 동작도 하지 않기 때문에 바로 return 해주는 동작을 수행
//8-2.c
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/types.h>
#include <linux/ioport.h>
MODULE_LICENSE("GPS");
MODULE_AUTHOR("BONITA");
MODULE_DESCRIPTION("Seven Segment LED");
#define base_lwFPGA 0xFF200000
#define len_lwFPGA 0x200000
#define addr_LED 0
#define addr_HEX0 0x20
#define addr_HEX1 0x30
#define addr_SW 0x40
#define addr_KEY 0x50
#define HEX_DEVMAJOR 240
#define HEX_DEVNAME "HEX"
static void *mem_base;
static void *hex0_addr; //hex3-hex0
static void *hex1_addr; //hex5-hex4
static unsigned int data = -1;
static unsigned int mode = 0;
#define NOFILL 4
#define BLINK 8
unsigned int hex0, hex1;
static int turnoff = 0;
int hex_conversion[16] = {
0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07,
0x7F, 0x67, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71
};
static int hex_open(struct inode *minode, struct file *mfile){return 0;}
static int hex_release(struct inode *minode, struct file *mfile){return 0;}
//write
static ssize_t hex_write(struct file *mfile, const char __user *buf, size_t count, loff_t *f_pos){
unsigned int hex_data = 0;
unsigned int nofill = 0;
get_user(hex_data, (unsigned int *)buf);
hex_data = hex_data & 0xFFFFFF;
data = hex_data;
if(mode & NOFILL) nofill = 1;
hex1 = 0;
hex0 = hex_conversion[hex_data&0xF];
do{
hex_data >>= 4;
if(nofill && hex_data==0) break;
hex0 |= hex_conversion[hex_data&0xF]<<8;
hex_data >>=4;
if(nofill && hex_data==0) break;
hex0 |= hex_conversion[hex_data&0xF]<<16;
hex_data >>=4;
if(nofill && hex_data==0) break;
hex0 |= hex_conversion[hex_data&0xF]<<24;
hex_data >>=4;
if(nofill && hex_data==0) break;
hex1 |= hex_conversion[hex_data&0xF];
hex_data >>=4;
if(nofill && hex_data==0) break;
hex1 |= hex_conversion[hex_data&0xF]<<8;
}while(0);
iowrite32(hex0, hex0_addr);
iowrite32(hex1, hex1_addr);
return 4;
}
//read
static ssize_t hex_read(struct file *mfile, const char __user *buf, size_t count, loff_t *f_pos){
put_user(data, (unsigned int*)buf);
return 4;
}
static long hex_ioctl(struct file *file, unsigned int cmd, unsigned long arg){
unsigned int newcmd;
mode = cmd;
return 0;
}
static struct file_operations hex_fops = {
.read = hex_read,
.write = hex_write,
.open = hex_open,
.release = hex_release
.unlocked_ioctl = hex_ioctl,
};
static int __init hex_init(void){
int res;
res = register_chrdev(HEX_DEVMAJOR, HEX_DEVNAME, &hex_fops);
if(res<0){
printk(KERN_ERR " HEX : failed to register device. \n");
return res;
}
mem_base = ioremap_nocache(base_lwFPGA, len_lwFPGA);
if(!mem_base){
printk("Error mapping memory.\n");
release_mem_region(base_lwFPGA, len_lwFPGA);
return -EBUSY;
}
printk("Device : %s / Major : %d \n\n\n", HEX_DEVNAME, HEX_DEVMAJOR);
hex0_addr = mem_base + addr_HEX0;
hex1_addr = mem_base + addr_HEX1;
return 0;
}
static void __exit hex_exit(void){
unregister_chrdev(HEX_DEVMAJOR, HEX_DEVNAME);
printk(" %s unregistered. \n\n", HEX_DEVNAME);
iowrite32(0, hex0_addr);
iowrite32(0, hex1_addr);
iounmap(mem_base);
}
module_init(hex_init);
module_exit(hex_exit);
$make
$insmod [filename.ko]
$lsmod
$mknod /dev/HEX c 240 0
//8-2-test.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#define NOFILL 4
#define BLINK 8
int main(void){
int dev, data, rdata;
dev = open("/dev/HEX", O_RDWR);
if(dev<0){
fprintf(stderr, "Cannot Open LED device.");
return 1;
}
//ioctl - default
ioctl(dev, 0, NULL);
//write
printf("Input HEX7 data (hex) : ");
scanf("%x", &data);
write(dev, &data, 4);
//read
read(dev, &rdata, 4);
printf("read data : %x \n", rdata);
//write - NOFILL
printf("Input HEX 7 data (hex) for NOFILL : ");
scanf("%x", &data);
ioctl(dev, NOFILL, NULL);
write(dev, &data, 4);
return 0;
}
https://butter-shower.tistory.com/31?category=715664
IOCTL 추가 설정 7segment led
http://csys.yonsei.ac.kr/lect/embed/e11.pdf